/**
 * Security helper functions for decrypting database credentials
 */
const crypto = require('crypto');
require('dotenv').config();

// Get the secret key from environment variables
const SECRET_KEY = process.env.SECRET_KEY;

// Get encrypted values from environment variables
const encryptedValues = {
  dbHost: process.env.ENCRYPTED_DB_HOST,
  dbName: process.env.ENCRYPTED_DB_NAME,
  dbTable: process.env.ENCRYPTED_DB_TABLE,
  dbUsername: process.env.ENCRYPTED_DB_USERNAME,
  dbPassword: process.env.ENCRYPTED_DB_PASSWORD
};

/**
 * Decrypt an encrypted string
 */
function decryptValue(encryptedText) {
  try {
    const parts = encryptedText.split(':');
    if (parts.length !== 3) return null; // Not our encrypted format
    
    const iv = Buffer.from(parts[0], 'hex');
    const authTag = Buffer.from(parts[1], 'hex');
    const encryptedData = parts[2];
    
    const decipher = crypto.createDecipheriv('aes-256-gcm', Buffer.from(SECRET_KEY, 'hex'), iv);
    decipher.setAuthTag(authTag);
    
    let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
    decrypted += decipher.final('utf8');
    
    return decrypted;
  } catch (error) {
    // If decryption fails, it's probably not our encrypted value
    return null;
  }
}

/**
 * Process function body to replace encrypted credentials with decrypted values
 */
function processEncryptedCredentials(functionBody) {
  if (!functionBody) return functionBody;
  
  let processedBody = functionBody;
  
  // Check for dynamic pattern matches first (hex:hex:hex)
  const encryptionPattern = /['"]([0-9a-f]+:[0-9a-f]+:[0-9a-f]+)['"]/g;
  let match;
  
  while ((match = encryptionPattern.exec(functionBody)) !== null) {
    const potentialEncrypted = match[1];
    const decrypted = decryptValue(potentialEncrypted);
    
    if (decrypted) {
      // Replace in the function body, keeping the quotes that surrounded it
      const fullMatch = match[0];
      const replacement = fullMatch[0] + decrypted + fullMatch[fullMatch.length - 1];
      processedBody = processedBody.replace(fullMatch, replacement);
    }
  }
  
  // Also check for known encrypted values
  Object.entries(encryptedValues).forEach(([key, encryptedValue]) => {
    if (processedBody.includes(encryptedValue)) {
      const decrypted = decryptValue(encryptedValue);
      if (decrypted) {
        processedBody = processedBody.replace(
          new RegExp(`['"]${encryptedValue}['"]`, 'g'), 
          `"${decrypted}"`
        );
      }
    }
  });
  
  return processedBody;
}

/**
 * NEW: Process and decrypt arguments array
 * Specifically designed to handle encrypted credentials passed as function arguments
 */
function processEncryptedArguments(args) {
  if (!Array.isArray(args)) return args;
  
  return args.map(arg => {
    // Check if this looks like an encrypted credential
    if (typeof arg === 'string' && arg.includes(':') && arg.length > 40) {
      const decrypted = decryptValue(arg);
      if (decrypted) {
        console.log(`[SECURITY-HELPERS] Successfully decrypted argument: ${arg.substring(0, 20)}...`);
        return decrypted;
      } else {
        console.log(`[SECURITY-HELPERS] Failed to decrypt argument: ${arg.substring(0, 20)}...`);
      }
    }
    return arg;
  });
}

/**
 * NEW: All-in-one function to process both function body and arguments
 */
function processAllEncryptedData(functionBody, args = []) {
  const processedBody = processEncryptedCredentials(functionBody);
  const processedArgs = processEncryptedArguments(args);
  
  return {
    processedBody,
    processedArgs
  };
}

module.exports = {
  decryptValue,
  processEncryptedCredentials,
  processEncryptedArguments,      // NEW
  processAllEncryptedData,        // NEW
  encryptedValues
};